package com.aspire.moss.portal.desktop;

import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup.OnHierarchyChangeListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Scroller;

import com.aspire.moss.portal.R;

public class Workspace extends ViewGroup implements
		OnHierarchyChangeListener, WorkspaceController {

	private static final String TAG = "Workspace";
	
	/**
	 * workspace最多可以容纳的页数
	 */
	public static final int MAX_PAGE = 10;

	private int screens; // 屏幕数

	private int mCurrentScreen;// 当前屏幕

	private boolean lock = false;

	/**
	 * 当在屏幕移动大于多少时 翻页
	 */
	private static int moveMin;

	private Context mContext;

	private Scroller mScroller;

	private VelocityTracker mVelocityTracker;
	
	private int lastx , downx , mTouchSlop;

	private WorkspaceListener workspaceListener;

	private WorkspaceAdapter workspaceAdapter;

	private WorkspaceAdapterObserver adapterObserver;
	
	private WorkspaceLock workspaceLock = new WorkspaceLock();
	/**
	 * 删除应用的动画
	 */
	private Animation delCellViewAnim ;

	int mWidth , mTouthX , downX = 0;

	public Workspace(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public Workspace(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mContext = context;
//		mScroller = new Scroller(mContext, AnimationUtils.loadInterpolator(
//				mContext, android.R.anim.accelerate_decelerate_interpolator));
		mScroller = new Scroller(mContext);
		this.setOnHierarchyChangeListener(this);
		adapterObserver = new WorkspaceAdapterObserver();
		final ViewConfiguration configuration = ViewConfiguration.get(context);
		mTouchSlop = configuration.getScaledTouchSlop();
		delCellViewAnim = AnimationUtils.loadAnimation(mContext, R.anim.scale);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		if (widthMode != MeasureSpec.EXACTLY) {
			throw new IllegalStateException(
					"Workspace can only be used in EXACTLY mode.");
		}
		mWidth = MeasureSpec.getSize(widthMeasureSpec);
		moveMin = mWidth / 3;
		for (int i = 0; i < getChildCount(); i++) {
			getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
		}
		setMeasuredDimension(resolveSize(mWidth, widthMeasureSpec), resolveSize(MeasureSpec.getSize(heightMeasureSpec), heightMeasureSpec));
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		int left = 0;
		View child = null;
		for (int i = 0; i < getChildCount(); i++) {
			child = getChildAt(i);
			child.layout(left, 0, left + child.getMeasuredWidth(), child
					.getMeasuredHeight());
			left += mWidth;
		}
	}

	@Override
	public void computeScroll() {
		super.computeScroll();
		Log.d(TAG, "mScroller.getCurrX()"+mScroller.getCurrX());
		if (mScroller.computeScrollOffset()) {
			scrollTo(mScroller.getCurrX(), 0);
			invalidate();
		}
	}

	@Override
	public void scrollTo(int x, int y) {
		mTouthX = x;
		super.scrollTo(x, y);
	}

	@Override
	public void scrollBy(int x) {
		scrollBy(x, 0);
		postInvalidate();
	}

	@Override
	public void scrollBy(int x, int y) {
		if ((getScrollX() <= 0 && Utils.isToRight(x))
				|| (getScrollX() >= (screens - 1) * mWidth && Utils.isToLeft(x))) {
			x /= 2;
		}
		super.scrollBy(x, y);
		mTouthX = getScrollX();
	}

	@Override
	public void scrollLeft() {
		Log.d(TAG, "scrollLeft");
		int target = 0;
		if (mCurrentScreen < screens - 1) {
			target = mCurrentScreen;
			target += 1;
		} else {
			target = mCurrentScreen;
		}
		scrollScreen(target);
	}

	@Override
	public void scrollRight() {
		Log.d(TAG, "scrollRight");
		int target = 0;
		if (mCurrentScreen != 0) {
			target = mCurrentScreen - 1;
		}
		scrollScreen(target);
	}

	/**
	 * 动画移动屏幕
	 * 
	 * @param screent
	 */
	public void scrollScreen(int screen) {
		Log.d(TAG, "scrollScreen = " + screen + "mCurrentScreen = "
				+ mCurrentScreen);
		final int target = (screen * mWidth);
		mScroller.startScroll(mTouthX, 0, (target - mTouthX), 0, 250);
		postInvalidate();
		if (mCurrentScreen != screen) {
			mCurrentScreen = screen;
			if (null != workspaceListener) {
				workspaceListener.onSelectScreenChange(mCurrentScreen);
			}
		}
	}

	/**
	 * 添加celllayout
	 */
	private void loadCellLayout() {
		for (int i = 0; i < workspaceAdapter.getCount(); i++) {
			addCellLayout(i);
		}
	}
	
	private void addCellLayout(int screenId){
		final CellLayout view = (CellLayout) workspaceAdapter.getGroupView(Workspace.this, screenId);
		if (view instanceof CellLayout) {
			view.screenId = screenId;
			addCelllayoutChild((CellLayout) view, screenId);
			addView(view, screenId);
		} else {
			Log.d(TAG, "add child view type is not Celllayou");
		}
	}
	

	/**
	 * 添加celllayout子控件
	 * 
	 * @param cellLayout
	 */
	private void addCelllayoutChild(CellLayout cellLayout, int group) {
		if(workspaceAdapter.getApps().size() <= group)
			return ;
		List<AppInfo> apps = workspaceAdapter.getApps().get(group);
		if (null == apps)
			return;
		AppView child = null;
		for (int i = 0; i < apps.size(); i++) {
			child = workspaceAdapter.getChildView(group, i);
			addChildToCelllayout(cellLayout, child);
		}
	}
	
	/**
	 * 子控件CellLayout添加AppView
	 * @param cellLayout
	 * @param child
	 */
	private void addChildToCelllayout(CellLayout cellLayout , AppView child){
		if(null == child || !(child instanceof AppView)){
			throw new IllegalArgumentException("chidl type not is a cellview");
		}
		workspaceLock.addObserver((Observer) child);
		child.appInfo.screen = cellLayout.screenId;//设置它的屏幕id
		if(isLockWorkspace()) child.update(null, lock);
		cellLayout.addView(child);
	}

	@Override
	public int getCurrentScreen() {
		return mCurrentScreen;
	}

	public void resetScreen() {
		scrollScreen(mCurrentScreen);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		final int e = event.getAction();
		final int x = (int) event.getX();
		acquireVelocityTrackerAndAddMovement(event);
		switch (e) {
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG, "MotionEvent.ACTION_DOWN x=" + x);
			downx = lastx = x;
			return true;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG, "MotionEvent.ACTION_MOVE x=" + x);
			int del = lastx - x;
			Log.d(TAG, "downx=" + downx + "del");
			lastx = x;
			scrollBy(del, 0);
			invalidate();
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG, "MotionEvent.ACTION_UP x=" + x);
			mVelocityTracker.computeCurrentVelocity(1000);
			Log.d("TAG", "VelocityTracker =" + mVelocityTracker.getXVelocity());
			float xVelocity = mVelocityTracker.getXVelocity();
			if ((downx - x) > moveMin
					|| (Math.abs(xVelocity) > Config.SNAP_VELOCITY && xVelocity < 0)) {
				scrollLeft();
			}else if ((downx - x) < 0 && Math.abs((downx - x)) > moveMin
					|| (Math.abs(xVelocity) > Config.SNAP_VELOCITY && xVelocity > 0)) {
				scrollRight();
			} else {
				resetScreen();
			}
			downx = 0;
			releaseVelocityTracker();
		default:
			break;
		}
		return true;
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		Log.d(TAG, "onInterceptTouchEvent ev= " + ev);
		boolean con = false;
		final int e = ev.getAction();
		final int x = (int) ev.getX();
		switch (e) {
		case MotionEvent.ACTION_UP:
			break;
		case MotionEvent.ACTION_DOWN:
			acquireVelocityTrackerAndAddMovement(ev);
			downx = lastx = x;
			return false;
		case MotionEvent.ACTION_MOVE:
			int diff = Math.abs(x - lastx);
			if (diff / 2 > mTouchSlop) {
				con = true;
			}
			Log.d(TAG, "con = " + con + "  diff=" + diff);
			return con;
		}
		return false;
	}

	private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(ev);
	}

	private void releaseVelocityTracker() {
		if (mVelocityTracker != null) {
			mVelocityTracker.recycle();
			mVelocityTracker = null;
		}
	}

	public void setWorkspaceListener(WorkspaceListener workspaceListener) {
		this.workspaceListener = workspaceListener;
	}
	
	/**
	 * 当添加一个页时,设置WorkspaceListener
	 */
	@Override
	public void onChildViewAdded(View parent, View child) {
		Log.d(TAG, "onChildViewAdded childs size=" + getChildCount());
		if (null != workspaceListener) {
			screens = getChildCount();
			workspaceListener.onScreenCountChange(screens);
		}
	}
	
	/**
	 * 当删除一个页时,设置WorkspaceListener
	 */
	@Override
	public void onChildViewRemoved(View parent, View child) {
		Log.d(TAG, "onChildViewRemoved childs size=" + workspaceListener);
		if (null != workspaceListener) {
			screens = getChildCount();
			workspaceListener.onScreenCountChange(screens);
		}
	}

	public void setWorkspaceAdapter(WorkspaceAdapter workspaceAdapter) {
		if (null != workspaceAdapter){
			this.workspaceAdapter = workspaceAdapter;
			this.workspaceAdapter.addObserver(adapterObserver);
		}
	}
	

	@Override
	public void lockWorkspace() {
		if(!lock){
			lock = true;
			workspaceLock.onChange(lock);
		}
	}

	@Override
	public void unlockWorkspace() {
		if(lock){
			lock = false;
			workspaceLock.onChange(lock);
			resetWorkspace();
		}
	}

	@Override
	public boolean isLockWorkspace() {
		return lock;
	}
	
	@Override
	public int getScreens() {
		return screens;
	}
	
	@Override
	public void addAppView(AppInfo appInfo) {
		LinkedList<AppInfo> group = workspaceAdapter.getGroup(appInfo.screen);
		if (null != group) {
			group.add(appInfo);
			AppView child = workspaceAdapter.getChildView(appInfo.screen,
					group.indexOf(appInfo));
			CellLayout cellLayout = findScreen(appInfo.screen);
			addChildToCelllayout(cellLayout, child);
		}
	}

	@Override
	public void addCelllayoutView() {
		int screenId = getChildCount();
		addCellLayout(screenId);
		workspaceAdapter.addGroupView(screenId);
	}

	@Override
	public CellLayout findScreen(int screenid) {
		CellLayout temp = null;
		for(int i = 0 ; i < getChildCount() ; i ++){
			temp = (CellLayout) getChildAt(i);
			if(temp.screenId == screenid) break;
		}
		return temp;
	}
	
	@Override
	public boolean removeAppView(AppInfo appInfo , int visible) {
		return removeAppView(appInfo, true , visible);
	}
	
	public void resetWorkspace(){
//		//for(int i = 0 ; i < )
	}
	
	private boolean removeAppView(AppInfo appInfo , boolean isAnim , int visible) {
		boolean con = false ;
		if(null != appInfo){
			final int screenId = appInfo.screen;
			final CellLayout cellLayout = findScreen(screenId);
			if(isAnim) {
				con = cellLayout.removeAppView(appInfo ,delCellViewAnim , visible);
			}else{
				con = cellLayout.removeAppView(appInfo ,null , visible);
			}
			
		}
		if(con) {
			workspaceAdapter.removeAppInfo(appInfo);//如果删除应用的视图成功,删除workspaceAdapter里的数据 
		}
		return con;
	}
	
	@Override
	public boolean moveAppView(AppInfo appInfo, AppInfo target) {
		final CellLayout ceLayout = findScreen(target.screen);
		if (null != ceLayout) {
			if (appInfo.eqXYScreen(target)) {// 不需要移动
				ceLayout.findAppView(target , GONE).setVisibility(VISIBLE);
			}else if(appInfo.screen == target.screen){
				final AppView cellView = (AppView) ceLayout.findAppView(appInfo,GONE);
				ceLayout.moveToXY(cellView, target.cellX, target.cellY, false);
				cellView.setVisibility(VISIBLE);
			}else {
				addAppView(target);
				removeAppView(appInfo, false ,GONE);
			}
		} else {
			return false;
		}

		return true;
	}
	
	@Override
	public boolean swapAppView(AppInfo appInfo, AppInfo target) {
		final CellLayout ceLayout = findScreen(target.screen);
		if (appInfo.screen == target.screen) { // 在当前页面进行移动,取得目标对的信息,如果目标存,则是交换位置,如果没有则是老自己移动到最一个
			final AppView cellView = (AppView) ceLayout.findAppView(appInfo,GONE);
			ceLayout.moveToXY(cellView, target.cellX, target.cellY, false);
			cellView.setVisibility(VISIBLE);
		}else{
			//这里是不同页面之间的交换
			//TODO 
		}
		return true;
	}
	
	
	
	/**
	 * 当工作空间的信息发生改变化时
	 * 
	 * @author Administrator
	 * 
	 */
	public interface WorkspaceListener {
		/**
		 * 当选中的屏幕发生变化时
		 * @param mCurrentScreen
		 */
		void onSelectScreenChange(int mCurrentScreen);

		/**
		 * 当屏幕数发生变化时
		 * @param count
		 */
		void onScreenCountChange(int count);
	}

	/**
	 * 用于监听数据适配器的变化
	 * @author Administrator
	 */
	private final class WorkspaceAdapterObserver implements Observer {

		@Override
		public void update(Observable observable, Object data) {
			/**
			 * 当数据适配器发生变化时,重新把界面刷新
			 */
			if (observable instanceof WorkspaceAdapter ) {
				removeAllViews();
				loadCellLayout();
			}
		}

	}
	
	/**
	 * 观察者模式,当worksapce锁定时
	 * @author Administrator
	 *
	 */
	private final class WorkspaceLock extends Observable {
		
		public void onChange(boolean con) {
			setChanged();
			notifyObservers(con);
		}
		
	}

	public void printInfo() {
		// TODO Auto-generated method stub
		
	}


}
